package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import com.zzyl.vo.QueryThingModelPublishedVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description DeviceServiceImpl
 * @Author 聆听
 * @Date 2025-09-10
 */
@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties; // 用于获取官方接口文档请求参数中的id
    @Autowired
    private Client client; // 引入了阿里云的SDK，通过 IotClientConfig 配置类创建的
    @Autowired
    private RedisTemplate<String, String> redisTemplate; // 操作缓存
    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 同步阿里云产品列表
     */
    @Override
    public void syncProductList() {
        // 封装请求参数
        QueryProductListRequest queryProductListRequest = new QueryProductListRequest();
        queryProductListRequest.setCurrentPage(1);
        queryProductListRequest.setPageSize(200); // 直接设置一页200条，一般产品数据不会超过200条，相当于全部同步过来
        queryProductListRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        // 调用第三方接口查询产品列表
        QueryProductListResponse response = null;
        try {
            response = client.queryProductList(queryProductListRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }

        // 接口是否返回成功
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        // 获取数据
        List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo()
                .stream()
                .map(p -> BeanUtil.toBean(p, ProductVo.class))
                .collect(Collectors.toList());
        // 存入Redis
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));
    }

    /**
     * 查询阿里云产品列表
     */
    @Override
    public List<ProductVo> allProduct() {
        // 从缓存中获取数据
        String result = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);

        // 如果返回的数据为空，说明还没有同步
        if (ObjectUtil.isEmpty(result)) {
            return Collections.emptyList(); // 工具类返回一个空集合，也可以手动new一个
        }

        // 将数据返回前，要转换成对象，现在是一个字符串
        return JSONUtil.toList(result, ProductVo.class);
    }

    /**
     * 新增产品
     */
    @Override
    public void addProduct(DeviceDto deviceDto) {
        // 检查设备是否重复
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }

        // 到阿里云创建新设备
        // 请求参数在传入的dto中就有，很奇怪
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = null; // 方便后文获取，try-catch中作用域不够
        try {
            response = client.registerDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        // 第三方接口是否调用成功
        if (!response.getBody().getSuccess()) {// 如果没有返回成功
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        // 补全产品的id，在阿里云创建过后才会生成这个id，要调接口去拿
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        // 判断是否调用成功
        if (!queryProductResponse.getBody().getSuccess()) {
            throw new RuntimeException(queryProductResponse.getBody().getErrorMessage());
        }

        // 封装pojo插入数据库
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        // 补全
        device.setProductName(queryProductResponse.getBody().getData().getProductName());
        device.setIotId(response.getBody().getData().getIotId()); // 创建产品后生成的id
        // 如果绑定的是随身设备，将绑定位置字段设为-1(默认为老人)
        if (device.getLocationType().equals(DeviceLocationEnum.PORTABLE_DEVICE.getOrdinal())) {
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        deviceMapper.insertSelective(device);

    }

    @Override
    public PageResponse<DeviceVo> findByPage(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        Page<DeviceVo> deviceVoPage = deviceMapper.selectByPage(devicePageQueryDto);
        return PageResponse.of(deviceVoPage, DeviceVo.class);
    }

    @Override
    public DeviceVo findByIdKey(QueryDeviceDetailRequest request) {
        // 根据iotId和productKey从第三方阿里云查询数据
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId()); // 有则必传
        QueryDeviceDetailResponse response = null;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        // 判断是否成功调用接口
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        // 根据iotId从数据库中查询字段信息
        // 直接用vo接收省去pojo的转换过程
        DeviceVo deviceVo =deviceMapper.selectByIotId(request.getIotId());
        // 调用工具类利用vo字段上的注解快速填充
        BeanUtil.copyProperties(response.getBody().getData(), deviceVo);

        return deviceVo;
    }

    @Override
    public QueryThingModelPublishedVo QueryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        // 根据productKey从阿里云查询物模型功能定义详情
        QueryThingModelPublishedResponse response = null;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }

        // 判断是否调用成功
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        // JSON -> 对象
        QueryThingModelPublishedVo queryThingModelPublishedVo = BeanUtil.toBean(response.getBody().getData(), QueryThingModelPublishedVo.class);

        // 返回
        return queryThingModelPublishedVo;
    }

    @Override
    public Object QueryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response = null;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        // 检查请求是否成功
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }


        return response.getBody().getData();

    }

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        // 先更新阿里云信息
        BatchUpdateDeviceNicknameRequest request_aliyun = new BatchUpdateDeviceNicknameRequest();
        // 创建信息列表
        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> infos = new ArrayList<>();

        // 设置设备信息
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo deviceNicknameInfo = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        deviceNicknameInfo.setDeviceName(deviceDto.getDeviceName());
        deviceNicknameInfo.setNickname(deviceDto.getNickname());
        deviceNicknameInfo.setProductKey(deviceDto.getProductKey());
        // 封装成list
        infos.add(deviceNicknameInfo);

        // 设置请求参数
        request_aliyun.setDeviceNicknameInfo(infos);
        request_aliyun.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameResponse response = null;
        try {
            response = client.batchUpdateDeviceNickname(request_aliyun);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        // 检查是否成功调用
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        // 再更新数据库
        // 先将 dto -> pojo
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        if (deviceMapper.updateByPrimaryKeySelective(device) <= 0) {
            throw new BaseException(BasicEnum.UPDATE_MYSQL);
        }

    }

    @Override
    public void deleteDevice(DeleteDeviceRequest deleteDeviceRequest) {
        // 根据iotId获取对象
        DeviceVo deviceVo = deviceMapper.selectByIotId(deleteDeviceRequest.getIotId());
        // 先删除数据库记录
        if (deviceMapper.deleteByPrimaryKey(deviceVo.getId()) < 0) {
            throw new BaseException(BasicEnum.DELETE_MYSQL);
        }

        // 再删除阿里云设备记录
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setIotId(deleteDeviceRequest.getIotId());
        request.setProductKey(deleteDeviceRequest.getProductKey());
        DeleteDeviceResponse response = null;
        try {
            response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }

        // 判断是否成功调用
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().errorMessage);
        }

    }
}
